package com.danciyixue.boot.dcyx.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.danciyixue.boot.client.test.model.PreTestSaveRequest;
import com.danciyixue.boot.client.testRecord.model.TestRecordSaveRequest;
import com.danciyixue.boot.core.security.util.SecurityUtils;
import com.danciyixue.boot.dcyx.service.UnitTestRecordsService;
import com.danciyixue.boot.dcyx.service.WordsService;
import com.danciyixue.boot.dcyx.service.UnitsService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.danciyixue.boot.dcyx.mapper.TestRecordsMapper;
import com.danciyixue.boot.dcyx.service.TestRecordsService;
import com.danciyixue.boot.dcyx.model.entity.TestRecords;
import com.danciyixue.boot.dcyx.model.form.TestRecordsForm;
import com.danciyixue.boot.dcyx.model.query.TestRecordsQuery;
import com.danciyixue.boot.dcyx.model.vo.TestRecordsVO;
import com.danciyixue.boot.dcyx.converter.TestRecordsConverter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Collectors;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;

/**
 * 测试结果记录服务实现类
 *
 * @author youlaitech
 * @since 2025-06-15 16:31
 */
@Service
@DS("dcyx")
@RequiredArgsConstructor
public class TestRecordsServiceImpl extends ServiceImpl<TestRecordsMapper, TestRecords> implements TestRecordsService {

    private final TestRecordsConverter testRecordsConverter;
    private final UnitTestRecordsService unitTestRecordsService;
    private final WordsService wordsService;
    private final UnitsService unitsService;

    /**
    * 获取测试结果记录分页列表
    *
    * @param queryParams 查询参数
    * @return {@link IPage<TestRecordsVO>} 测试结果记录分页列表
    */
    @Override
    public IPage<TestRecordsVO> getTestRecordsPage(TestRecordsQuery queryParams) {
        Page<TestRecordsVO> pageVO = this.baseMapper.getTestRecordsPage(
                new Page<>(queryParams.getPageNum(), queryParams.getPageSize()),
                queryParams
        );
        return pageVO;
    }
    
    /**
     * 获取测试结果记录表单数据
     *
     * @param id 测试结果记录ID
     * @return 测试结果记录表单数据
     */
    @Override
    public TestRecordsForm getTestRecordsFormData(Long id) {
        TestRecords entity = this.getById(id);
        return testRecordsConverter.toForm(entity);
    }
    
    /**
     * 新增测试结果记录
     *
     * @param formData 测试结果记录表单对象
     * @return 是否新增成功
     */
    @Override
    public boolean saveTestRecords(TestRecordsForm formData) {
        TestRecords entity = testRecordsConverter.toEntity(formData);
        return this.save(entity);
    }
    
    /**
     * 更新测试结果记录
     *
     * @param id   测试结果记录ID
     * @param formData 测试结果记录表单对象
     * @return 是否修改成功
     */
    @Override
    public boolean updateTestRecords(Long id,TestRecordsForm formData) {
        TestRecords entity = testRecordsConverter.toEntity(formData);
        return this.updateById(entity);
    }
    
    /**
     * 删除测试结果记录
     *
     * @param ids 测试结果记录ID，多个以英文逗号(,)分割
     * @return 是否删除成功
     */
    @Override
    public boolean deleteTestRecordss(String ids) {
        Assert.isTrue(StrUtil.isNotBlank(ids), "删除的测试结果记录数据为空");
        // 逻辑删除
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(Long::parseLong)
                .toList();
        return this.removeByIds(idList);
    }

    /**
     * 检查用户是否已完成指定教材的学前测试
     *
     * @param userId 用户ID
     * @param programId 教材ID
     * @return 是否已完成学前测试
     */
    @Override
    public boolean hasCompletedPreTest(Long userId, Long programId) {
        // 学前测试类型为1
        long count = this.count(new LambdaQueryWrapper<TestRecords>()
                .eq(TestRecords::getUserId, userId)
                .eq(TestRecords::getProgramId, programId)
                .eq(TestRecords::getType, 1));
        return count > 0;
    }

    /**
     * 通过教材ID查询测试记录VO
     *
     * @param programId 教材ID
     * @return 测试记录VO对象，如果未完成测试则返回null
     */
    @Override
    public TestRecordsVO getTestRecordsByProgramId(Long programId) {
        // 从 SecurityUtils 中获取当前用户ID
        Long userId = SecurityUtils.getUserId();
//        if (userId == null) {
//            return null;
//        }

        // 学前测试类型为1，查询测试记录VO
        return this.baseMapper.findTestRecordsVOByUserIdAndProgramIdAndType(userId, programId, 1);
    }

    /**
     * 保存学前测试记录
     *
     * @param request 学前测试保存请求对象
     * @return 是否保存成功
     */
    @Override
    public boolean savePreTestRecord(PreTestSaveRequest request) {
        // 从 SecurityUtils 中获取当前用户ID
        Long userId = SecurityUtils.getUserId();
//        if (userId == null) {
//            throw new RuntimeException("用户未登录");
//        }

        // 按照 programId 和 userId 查询 TestRecords 表
        TestRecords existingRecord = this.baseMapper.findByUserIdAndProgramIdAndType(
                userId, request.getProgramId(), request.getType());
        /* 学前测试 type 设为 1 */
        request.setType(1);
        if (existingRecord != null) {
            // 如果存在则更新
            return updateExistingRecord(existingRecord, request, userId);
        } else {
            // 不存在则插入
            return insertNewRecord(request, userId);
        }
    }

    /**
     * 更新现有测试记录
     */
    private boolean updateExistingRecord(TestRecords existingRecord, PreTestSaveRequest request, Long userId) {
        existingRecord.setSeriesId(request.getSeriesId());
        existingRecord.setProgramId(request.getProgramId());
        existingRecord.setUserId(userId);
        existingRecord.setTestId(request.getTestId());
        existingRecord.setQuestionNumber(request.getQnumber());
        existingRecord.setRemark(request.getRemark());
        existingRecord.setScore(request.getScore());
        // 将毫秒转换为秒
        existingRecord.setTimeConsuming((int) (request.getTimeConsuming() / 1000));
        existingRecord.setType(request.getType());
        return this.updateById(existingRecord);
    }

    /**
     * 插入新测试记录
     */
    private boolean insertNewRecord(PreTestSaveRequest request, Long userId) {
        TestRecords testRecord = new TestRecords();
        testRecord.setSeriesId(request.getSeriesId());
        testRecord.setProgramId(request.getProgramId());
        testRecord.setUserId(userId);
        testRecord.setTestId(request.getTestId());
        testRecord.setQuestionNumber(request.getQnumber());
        testRecord.setRemark(request.getRemark());
        testRecord.setScore(request.getScore());
        // 将毫秒转换为秒
        testRecord.setTimeConsuming((int) (request.getTimeConsuming() / 1000));
        testRecord.setType(request.getType());
        return this.save(testRecord);
    }

    /**
     * 保存测试记录信息
     *
     * @param request 测试记录保存请求对象
     * @return 是否保存成功
     */
    @Override
    public boolean saveTestRecord(TestRecordSaveRequest request) {
        // 从 SecurityUtils 中获取当前用户ID
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            throw new RuntimeException("用户未登录");
        }

        try {
            // 1. 保存或更新单元测试记录
            boolean unitTestResult = unitTestRecordsService.saveOrUpdateUnitTestRecord(
                    userId,
                    request.getUnitId(),
                    request.getScore(),
                    request.getTimeSpent(),
                    1 // 设置为已完成
            );

            // 2. 保存或更新测试记录
            boolean testRecordResult = saveOrUpdateTestRecord(request, userId);

            return unitTestResult && testRecordResult;
        } catch (Exception e) {
            throw new RuntimeException("保存测试记录失败: " + e.getMessage(), e);
        }
    }

    /**
     * 保存或更新测试记录
     */
    private boolean saveOrUpdateTestRecord(TestRecordSaveRequest request, Long userId) {
        // 根据 userId 和 testId 查询现有记录
        TestRecords existingRecord = this.baseMapper.findByUserIdAndTestId(userId, request.getTestId());

        if (existingRecord != null) {
            // 如果存在则更新
            return updateExistingTestRecord(existingRecord, request, userId);
        } else {
            // 不存在则插入
            return insertNewTestRecord(request, userId);
        }
    }

    /**
     * 更新现有测试记录
     */
    private boolean updateExistingTestRecord(TestRecords existingRecord, TestRecordSaveRequest request, Long userId) {
        existingRecord.setUserId(userId);
        existingRecord.setUnitId(request.getUnitId());
        existingRecord.setTestId(Long.valueOf(request.getTestId()));
        existingRecord.setScore(request.getScore());
        existingRecord.setTimeConsuming(request.getTimeSpent());
        existingRecord.setWrongWordIds(request.getWrongWordIds());
        existingRecord.setRightWordIds(request.getRightWordIds());
        existingRecord.setUnchooseWordIds(request.getUnchooseWordIds());
        existingRecord.setType(2);
        return this.updateById(existingRecord);
    }

    /**
     * 插入新测试记录
     */
    private boolean insertNewTestRecord(TestRecordSaveRequest request, Long userId) {
        TestRecords testRecord = new TestRecords();
        testRecord.setUserId(userId);
        testRecord.setUnitId(request.getUnitId());
        testRecord.setTestId(Long.valueOf(request.getTestId()));
        testRecord.setScore(request.getScore());
        testRecord.setTimeConsuming(request.getTimeSpent());
        testRecord.setWrongWordIds(request.getWrongWordIds());
        testRecord.setRightWordIds(request.getRightWordIds());
        testRecord.setUnchooseWordIds(request.getUnchooseWordIds());
        testRecord.setType(2);
        return this.save(testRecord);
    }

    /**
     * 根据教材ID查询用户的测试记录列表
     *
     * @param programId 教材ID
     * @return 测试记录列表，包含单词拼写信息
     */
    @Override
    public List<TestRecordsVO> getTestRecordsListByProgramId(Long programId) {
        // 从 SecurityUtils 中获取当前用户ID
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return new ArrayList<>();
        }

        // 先根据 programId 查询该教材下的所有 unitId
        List<Long> unitIds = unitsService.getUnitIdsByProgramId(programId);
        if (unitIds == null || unitIds.isEmpty()) {
            return new ArrayList<>();
        }

        // 根据 userId 和 unitId 列表查询测试记录
        List<TestRecordsVO> testRecords = this.baseMapper.findTestRecordsByUserIdAndUnitIds(userId, unitIds);

        // 为每个测试记录填充单词拼写信息
        for (TestRecordsVO record : testRecords) {
            populateWordSpellings(record);
        }

        return testRecords;
    }

    /**
     * 为测试记录填充单词拼写信息
     *
     * @param record 测试记录VO
     */
    private void populateWordSpellings(TestRecordsVO record) {
        // 处理错误单词拼写
        record.setWrongWordSpellings(getWordSpellingsFromIds(record.getWrongWordIds()));

        // 处理正确单词拼写
        record.setRightWordSpellings(getWordSpellingsFromIds(record.getRightWordIds()));

        // 处理未选择单词拼写
        record.setUnchooseWordSpellings(getWordSpellingsFromIds(record.getUnchooseWordIds()));
    }

    /**
     * 根据单词ID字符串获取单词拼写列表
     *
     * @param wordIdsStr 单词ID字符串，逗号分隔
     * @return 单词拼写列表
     */
    private List<String> getWordSpellingsFromIds(String wordIdsStr) {
        if (wordIdsStr == null || wordIdsStr.trim().isEmpty()) {
            return new ArrayList<>();
        }

        try {
            List<Long> wordIds = Arrays.stream(wordIdsStr.split(","))
                    .map(String::trim)
                    .filter(s -> !s.isEmpty())
                    .map(Long::parseLong)
                    .collect(Collectors.toList());

            return wordsService.getWordSpellingsByIds(wordIds);
        } catch (NumberFormatException e) {
            // 如果解析失败，返回空列表
            return new ArrayList<>();
        }
    }

}
